namespace pdfviewnet
{

using namespace System;
using namespace System::Globalization;
using namespace System::Text;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Collections::Generic;
using namespace System::Threading;
using namespace System::Windows;
using namespace System::Windows::Input;
using namespace System::Windows::Controls;
using namespace System::Windows::Media::Imaging;
using namespace System::Windows::Media::Animation;
using namespace System::Windows::Media;
using namespace System::Runtime::InteropServices;
using namespace System::Text::RegularExpressions;


	static const int iSuffix = 3;
	static const int iWholeword = 2;
	ref class ImageControl;

	ref class Result
	{
	public:
		Result(Match^ match)
		{
			Match = match;
			suffix = match->Groups[iSuffix]->ToString();
		}
		Match^ Match;
		String^ suffix;
		int count;
	};



	public ref class BookMark
	{
	public:
		BookMark(int page, String^ matchcontext, String^ pattern, bool exact)
		{
			this->page = page;
			this->matchcontext = matchcontext;
			this->pattern = pattern;
			this->exact = exact;
		}
		int page;
		bool exact;
		String^ matchcontext;
		String^ pattern;
	};




	ref class SearchWorker : public BackgroundWorker
	{
	private:
		ImageControl^ mycontrol;
	public:
		SearchWorker(ImageControl^ control)
		{
			mycontrol = control;
			WorkerReportsProgress = true;
			WorkerSupportsCancellation = true;
		}


	protected:
		static String^ Pattern(String^ searchtext)
		{
			//group 1          2                                 3
			return "([\\s,\\W])(" + Regex::Escape(searchtext) + "(\\w*))(\\s|\\W)";		
		};	

		virtual void OnDoWork(DoWorkEventArgs^ e) override;

		static System::String^ GetBookmarkText(MatchCollection^ matches, String^ searchText)
		{
			Dictionary<String^, Result^>^ dict = gcnew Dictionary<String^, Result^>();			
			Match^ firstItem = matches[0];

			String^ countSuffix = (matches->Count <= 1) ? "" : " (" + matches->Count.ToString() + "x)";

			for each(Match^ match in matches)
			{			
				if (match->Groups[iSuffix]->Length < firstItem->Groups[iSuffix]->Length || searchText == match->Groups[iWholeword]->ToString())
				{
					firstItem = match;
				}

				String^ text = match->Groups[iWholeword]->ToString()->ToLower(CultureInfo::CurrentUICulture);

				if (!dict->ContainsKey(text))
				{
					dict->Add(text, gcnew Result(match));						
				}

				dict[text]->count += 1;
			}					

			StringBuilder^ builder = gcnew StringBuilder();

			builder->Append(firstItem->Groups[iWholeword]->ToString());

			for each(KeyValuePair<String^, Result^>^ pair in dict)
			{					
				if (pair->Value->Match == firstItem)
					continue;

				if (pair->Value->suffix->Length == 0)
					continue;

				builder->Append(", ~");						
				builder->Append(pair->Value->suffix);						
			}

			return builder->ToString() + countSuffix;									
		}

		static bool IsExact(MatchCollection^ matches, String^ searchText)
		{
			for each(Match^ match in matches)
			{			
				String^ text = match->Groups[iWholeword]->ToString();
				if (text == searchText)
					return true;
			}
			return false;
		}

	};

}